package org.tinygroup.menuframe.util;


import org.apache.commons.lang.StringUtils;
import org.tinygroup.logger.LogLevel;
import org.tinygroup.logger.Logger;
import org.tinygroup.logger.LoggerFactory;
import org.tinygroup.menuframe.config.Menu;
import org.tinygroup.menuframe.dto.MenuInfo;
import org.tinygroup.menuframe.dto.MenuNode;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Created by wangwy11342 on 2016/7/29.
 */
public class MenuUtil {
	
	private static final Logger logger = LoggerFactory.getLogger(MenuUtil.class);
	
    public MenuNode[] toTree(Integer[] menuIds,
                             Menu[] menus) {
        if (menuIds == null) {
            return new MenuNode[0];
        }
        // 存放所有的已经权限菜单
        Map<Integer, MenuNode> nodeMap = new HashMap<Integer, MenuNode>();
        for (Menu tsysMenu : menus) {
            MenuNode node = new MenuNode(tsysMenu.getId(), tsysMenu);
            nodeMap.put(node.getId(), node);
        }
        // 存放已计算过的节点Id
        List<Integer> computedIds = new ArrayList<Integer>();
        // 存放已计算过的节点
        Map<Integer, MenuNode> computedNodes = new HashMap<Integer, MenuNode>();
        for (Integer menuId : menuIds) {
            if(!nodeMap.containsKey(menuId)){
                //排除未被授权的菜单
                continue;
            }
            MenuNode node = nodeMap.get(menuId);
//            logger.logMessage(LogLevel.WARN, "已授权--->{0}",node.getId());
//            MenuNode node = new MenuNode(userMenu.getId(), userMenu);
            computed(node, computedIds, computedNodes, nodeMap);
        }
        return toArray(computedNodes);
    }
    
    private static void addMenu(MenuNode mn ,List<Menu> lsMenu){
		Menu menu= (Menu)mn.getInfo();
		lsMenu.add(menu);
		List<MenuNode> subNodes = mn.getSubNode();
    	if(null != subNodes && subNodes.size()>0){
    		for(MenuNode m : subNodes){
    			addMenu(m,lsMenu);
    		}
    	}
	}
    
    /**
     * 将树状的MenuInfo对象转换为menu列表
     * @param menuInfo
     * @return
     */
    public static List<Menu> toList(MenuInfo menuInfo){
    	List<MenuNode> lsMenu = menuInfo.getMenuList();
        List<Menu> menuList = new ArrayList<Menu>();
        for(MenuNode m : lsMenu){
        	addMenu(m,menuList);
        }
        return menuList;
    }

    protected MenuNode[] toArray(Map<Integer, MenuNode> computedNodes) {
        List<MenuNode> list = new ArrayList<MenuNode>();
        for (MenuNode node : computedNodes.values()) {
            Menu tsysMenu = (Menu) node.getInfo();
            if (tsysMenu.getParentId()==null || tsysMenu.getParentId() == 0) {
                list.add(node);
                continue;
            }
        }
        MenuNode[] tree = new MenuNode[list.size()];
        int i = 0;
        for (MenuNode node : list) {
            tree[i] = node;
            i++;
        }
        return tree;
    }

    protected void computed(MenuNode node, List<Integer> computedIds,
                            Map<Integer, MenuNode> computedNodes, Map<Integer, MenuNode> nodeMap) {
        Integer id = node.getId();
        if (computedNodes.containsKey(id)) {
            return;
        }
        // 如果没算过，就把他存放到已算列表
        computedNodes.put(id, node);
        computedIds.add(id);
        // 然后计算该节点的父节点
        Menu tsysMenu = (Menu) node.getInfo();
        Integer parentId  = null;
        if(tsysMenu.getParentId()!=null && tsysMenu.getParentId()!=0){
            parentId = Integer.valueOf(tsysMenu.getParentId());
        }
        if (parentId == null || parentId==0) {
            return;
        }
        Menu parent = (Menu) nodeMap.get(parentId).getInfo();
        MenuNode nodeParent = computedNodes.get(parentId);
        if (nodeParent == null) {
            nodeParent = new MenuNode(parentId, parent);
        }
        nodeParent.getSubNode().add(node);
        logger.warnMessage("计算菜单节点树:{}", id);
        computed(nodeParent, computedIds, computedNodes, nodeMap);

    }

    public MenuNode[] toTreeByList(List<Integer> tUserTFunctionIds, List<Menu> tFunctions){
        Integer[] userFunctionIdArray = new Integer[tUserTFunctionIds!=null?tUserTFunctionIds.size():0];
        Menu[] tFunctionArray = new Menu[tFunctions!=null?tFunctions.size():0];
        tUserTFunctionIds.toArray(userFunctionIdArray);
        tFunctions.toArray(tFunctionArray);
        return toTree(userFunctionIdArray , tFunctionArray);
    }

    /**
     * 计算当前URL对应的菜单所在路径
     * @param treeNodes
     * @param currentUrl
     * @param pathList
     */
    public void getSelectedPath(List<MenuNode> treeNodes, String currentUrl,
                                List<Integer> pathList){
        Map<Integer,Integer> fetchMap = new HashMap<Integer, Integer>();
        
        Map<Integer,Integer> fetchCores = new HashMap<Integer, Integer>();
        
        //获取当前URL对应的菜单Id，并设置菜单对应的父节点
        fetch(treeNodes,currentUrl,fetchMap,fetchCores);
        
        Iterator<Integer> itr = fetchCores.keySet().iterator();
        Integer lastId=null;
        int score = 0;
        Integer selId =null;
        while(itr.hasNext()){
        	Integer keyId = itr.next();
        	int scoreThis = fetchCores.get(keyId);
        	
//        	System.out.println(score+"==="+scoreThis+"-s--"+keyId);
        	if(scoreThis > score){
        		selId = keyId;
        		lastId = selId;
        		score = scoreThis;
        	}
        	else if(lastId != null && scoreThis == score){
        		selId = lastId;
        	}
        }
        
//        System.out.println(score+"==="+"-s--"+selId);
        
        if(selId==null) {
            fetchDefaultPath(treeNodes,pathList);
        }else {
            getPath(fetchMap, pathList, selId);
        }
    }

    private void fetchDefaultPath(List<MenuNode> treeNodes, List<Integer> pathList) {
        List<MenuNode> curTreeNodes = treeNodes;
        while(curTreeNodes.size()>0){
            MenuNode treeNode = curTreeNodes.get(0);
            pathList.add(treeNode.getId());
            curTreeNodes = treeNode.getSubNode();
        }
    }

    private void getPath(Map<Integer, Integer> fetchMap,List<Integer> pathList, Integer selId) {
        if(selId==null || selId==0){
            return;
        }
        pathList.add(selId);
        Integer pid = fetchMap.get(selId);
        //迭代获取path
        while(pid!=null && pid!=0){
            pathList.add(0,pid);
            pid = fetchMap.get(pid);
        }
    }
    
    /**
     * 获取当前URL对应的菜单Id，并设置菜单对应的父节点
     * @param treeNodes
     * @param currentUrl
     * @param fetchMap
     * @return
     */
    private void fetch(List<MenuNode> treeNodes, String currentUrl, Map<Integer,Integer> fetchMap,Map<Integer,Integer> fetchCores ) {
    	
    	if(treeNodes == null ){
    		return;
    	}
        for(MenuNode treeNode : treeNodes){
            Menu sysMenuExt = (Menu)treeNode.getInfo();
            String menuUrl = sysMenuExt.getUrl();
//            logger.logMessage(LogLevel.WARN, "授权菜单:{0}",menuUrl);
            //去掉page后缀
            if (menuUrl.endsWith(".page")) {
                int index = menuUrl.lastIndexOf(".page");
                menuUrl = menuUrl.substring(0, index);
            }
            if (currentUrl.endsWith(".page")) {
                int index = currentUrl.lastIndexOf(".page");
                currentUrl = currentUrl.substring(0, index);
            }
            
            Integer[] weights =new Integer[]{20,10,5,2};
            
            //对URL进行匹配度评分
            String[] curPaths = currentUrl.split("/");
            String[] menuPaths = menuUrl.split("/");
            Integer score =0;
            int min= Math.min(curPaths.length, menuPaths.length);
            for(int i =0 ; i<min ; i++){
            	if(StringUtils.isEmpty(menuPaths[i].trim())){
            		continue;
            	}
            	if( curPaths[i].equals(menuPaths[i])){
//            		System.out.println(menuPaths[i]+"====="+curPaths[i]);
            		score += (i < weights.length ? weights[i] : 1);
            	}
            	else{
            		break;
            	}
            }
            if(fetchCores.containsKey(sysMenuExt.getId())){
            	logger.logMessage(LogLevel.WARN, "重复????{0},{1}",fetchCores.get(sysMenuExt.getId()),score);
            	fetchCores.put(sysMenuExt.getId(), score+fetchCores.get(sysMenuExt.getId()));
            }
            else{
              fetchCores.put(sysMenuExt.getId(), score);
            }
            //如果是下级，设置对应的上级菜单
            if(sysMenuExt.getParentId()!=null && sysMenuExt.getParentId()!=0){
                fetchMap.put(treeNode.getId(),sysMenuExt.getParentId());
            }
            //如果已经是叶子菜单节点
            if(treeNode.getSubNode()!=null && treeNode.getSubNode().size() > 0) {
            	fetch(treeNode.getSubNode(), currentUrl, fetchMap,fetchCores);
            }
            
        }
    }


}
